DinkLua Object Reference

Introduction

This is a brief guide containing a reference of object methods in DinkLua. It assumes you've read the introduction from the author, and also have existing knowledge of DinkC/how the engine works, as well as some basic familiarity with object-oriented principles.

These can be troublesome as object function methods use the : semicolon operator, rather than dot as is used for table functions and therefore may be quite confusing.

Sprites

Sprites are created using the create_sprite function as part of the "dink" table. Most DinkC-equivalent features are also under this table, however in the case of sprite properties, they are altered like so:

mysprite = dink.create_sprite(100, 100, 0, 100, 1)
myothersprite = dink.create_sprite(120, 120, 6, 200, 1)
-- add 5 to sprite's position
mysprite.x = mysprite.x + 5
mysprite.y = 110
-- set sprite to not clip
mysprite.noclip = true
mysprite = dink.create_sprite(100, 100, 0, 100, 1)
myothersprite = dink.create_sprite(120, 120, 6, 200, 1)
-- add 5 to sprite's position
mysprite.x = mysprite.x + 5
mysprite.y = 110
-- set sprite to not clip
mysprite.noclip = true

The rest of the sprite properties include:

mysprite.active = false
mysprite.attack_hit_sound = 44
mysprite.attack_hit_sound_speed = 96000
mysprite.attack_wait = 10
mysprite.base_attack = 450
mysprite.base_die = 200
mysprite.base_death = 200
mysprite.base_hit = 100
mysprite.base_idle = 10
mysprite.base_walk = 20
mysprite.brain = brain.REPEAT or 6
mysprite.brain_parm = 5
mysprite.brain_parm2 = 10
mysprite.defense = 100
mysprite.dir = direction.SOUTH or 2
mysprite.disabled = false
mysprite.distance = 100
mysprite.exp = 5000
mysprite.flying = true
mysprite.follow = myothersprite
mysprite.frame = 1
mysprite.seq = 100
mysprite.frame_delay = 33
mysprite.gold = 9000
mysprite.hard = true
mysprite.hitpoints = 5
mysprite.move_nohard = true
mysprite.mx = 4
mysprite.my = 5
mysprite.nocontrol = true
mysprite.nodraw = false
mysprite.nohit = true
mysprite.notouch = false
mysprite.pframe = 3
mysprite.picfreeze = true
mysprite.pseq = 450
mysprite.que = -1000
mysprite.range = 10
mysprite.reverse = true
mysprite.size = 150
mysprite.sound = 20
mysprite.strength = 200
mysprite.target = myothersprite
mysprite.timing = 66
mysprite.touch_damage = -1
mysprite.kill = 1000
mysprite.freeze = true
mysprite.custom["key"] = 121
mysprite.custom.otherkey = 212
mysprite.active = false
mysprite.attack_hit_sound = 44
mysprite.attack_hit_sound_speed = 96000
mysprite.attack_wait = 10
mysprite.base_attack = 450
mysprite.base_die = 200
mysprite.base_death = 200
mysprite.base_hit = 100
mysprite.base_idle = 10
mysprite.base_walk = 20
mysprite.brain = brain.REPEAT or 6
mysprite.brain_parm = 5
mysprite.brain_parm2 = 10
mysprite.defense = 100
mysprite.dir = direction.SOUTH or 2
mysprite.disabled = false
mysprite.distance = 100
mysprite.exp = 5000
mysprite.flying = true
mysprite.follow = myothersprite
mysprite.frame = 1
mysprite.seq = 100
mysprite.frame_delay = 33
mysprite.gold = 9000
mysprite.hard = true
mysprite.hitpoints = 5
mysprite.move_nohard = true
mysprite.mx = 4
mysprite.my = 5
mysprite.nocontrol = true
mysprite.nodraw = false
mysprite.nohit = true
mysprite.notouch = false
mysprite.pframe = 3
mysprite.picfreeze = true
mysprite.pseq = 450
mysprite.que = -1000
mysprite.range = 10
mysprite.reverse = true
mysprite.size = 150
mysprite.sound = 20
mysprite.strength = 200
mysprite.target = myothersprite
mysprite.timing = 66
mysprite.touch_damage = -1
mysprite.kill = 1000
mysprite.freeze = true
mysprite.custom["key"] = 121
mysprite.custom.otherkey = 212

And so on and so on. sniffs

Values can also be retrieved like so:

local x = mysprite.x
dink.debug(x)
-- will emit 105 to the debug output
local x = mysprite.x
dink.debug(x)
-- will emit 105 to the debug output

As is usual in the world of Dink, most things don't make sense, and several other sprite modifications are performed with methods, along with the usual fare such as for talking and moving:

mysprite:freeze()
mysprite:unfreeze()
mysprite:kill_wait()
mysprite:say("hi")
mysprite:say_stop("bye")
myothersprite:say_stop_npc("quack")
mysprite:move(direction.SOUTH, 100, true)
mysprite:move_stop(direction.NORTH, 100, false)
mysprite:draw_hard()
mysprite:hurt(5)
mysprite:kill_shadow()
mysprite:freeze()
mysprite:unfreeze()
mysprite:kill_wait()
mysprite:say("hi")
mysprite:say_stop("bye")
myothersprite:say_stop_npc("quack")
mysprite:move(direction.SOUTH, 100, true)
mysprite:move_stop(direction.NORTH, 100, false)
mysprite:draw_hard()
mysprite:hurt(5)
mysprite:kill_shadow()

These can also be used on the convenience variables of current_sprite and player with the latter having a few specific ones of its own:

player:set_speed(5)
player.get_speed
player.can_walk_off_screen = true
player.base_push = 500
player:set_speed(5)
player.get_speed
player.can_walk_off_screen = true
player.base_push = 500

Sound effects

Sound effects invoked with dink.playsound() will similarly return an object that has modifiable properties:

mysound = dink.playsound(44)
mysound.vol = 50
-- half volume
mysound.survive = true
mysound.pan = -10
-- to the left a little
mysound.hz = 22050
mysound.speed = 10
mysound.pause = true
mysound.looppoint = 4
mysound.repeating = true
mysound = dink.playsound(44)
mysound.vol = 50
-- half volume
mysound.survive = true
mysound.pan = -10
-- to the left a little
mysound.hz = 22050
mysound.speed = 10
mysound.pause = true
mysound.looppoint = 4
mysound.repeating = true

Along with some that only return a value

local count = mysound.loopcount
local position = mysound.pos
local count = mysound.loopcount
local position = mysound.pos

And similarly have some methods:

mysound:kill()
mysound:fade_vol(90, 2)
-- 90% volume over two seconds
mysound:fade_pan(50, 5)
-- half to the right over 5 seconds
mysound:fade_speed(10, 5)
-- 10% speed over 5 seconds
mysound:schedule_pause(5)
mysound:schedule_stop(8)
mysound:oscillate_pan(-10, 0, 3)
-- to the left and to centre over 3 seconds
mysound:oscillate_vol(80, 90, 5)
mysound:oscillate_speed(10, 100, 9)
mysound:kill()
mysound:fade_vol(90, 2)
-- 90% volume over two seconds
mysound:fade_pan(50, 5)
-- half to the right over 5 seconds
mysound:fade_speed(10, 5)
-- 10% speed over 5 seconds
mysound:schedule_pause(5)
mysound:schedule_stop(8)
mysound:oscillate_pan(-10, 0, 3)
-- to the left and to centre over 3 seconds
mysound:oscillate_vol(80, 90, 5)
mysound:oscillate_speed(10, 100, 9)

Please see below for the sound effect global object in 0.93.

Global variables

Creating and accessing global variables is accomplished using the "global" table.

Creation:

global.create("name", 0)
global.create("name", 0)

Changing the value:

global.name = 5
global.name = 5

Choice menus

Creation is performed by creating a menu object, adding choices to it, and then showing it, with the result stored in a new variable.

local menu = dink.create_choice_menu()
-- change params before showing it
menu.y = 100
menu.title = "Hello!"
menu.title_color = 5

-- add some choices
local what = menu:add_choice("What is going on?")
local where = menu:add_choice("Where am I?")

local mychoice = menu:show()

if mychoice == what then
    current_sprite:say("I don't know")
end

if mychoice == where then
    current_sprite:say("It is a mystery")
end
local menu = dink.create_choice_menu()
-- change params before showing it
menu.y = 100
menu.title = "Hello!"
menu.title_color = 5

-- add some choices
local what = menu:add_choice("What is going on?")
local where = menu:add_choice("Where am I?")

local mychoice = menu:show()

if mychoice == what then
    current_sprite:say("I don't know")
end

if mychoice == where then
    current_sprite:say("It is a mystery")
end

Editor sprite overrides

Accessed by creating an object out of a sprite that has a corresponding editor sprite, and then altering its parameters.

local myoverride = current_sprite.editor_sprite
myoverride.seq = 1
myoverride.frame = 10
myoverride.type = editor_type.KILL_RETURN_AFTER_ONE_MINUTE
local myoverride = current_sprite.editor_sprite
myoverride.seq = 1
myoverride.frame = 10
myoverride.type = editor_type.KILL_RETURN_AFTER_ONE_MINUTE

Helpers

Brain reference

These may be passed to a sprite's brain parameter when prefixed with "brain" instead of using the number:

      NONE = 0,
      PLAYER = 1,
      DUMB_SPRITE_BOUNCER = 2,
      DUCK = 3,
      PIG = 4,
      KILL_SEQ_DONE_LEAVE_LAST_FRAME = 5,
      REPEAT = 6,
      KILL_SEQ_DONE = 7,
      TEXT_SPRITE = 8,
      MONSTER_DIAGONAL = 9,
      MONSTER_NONDIAGONAL = 10,
      MISSILE = 11,
      BRAIN_PARM_SIZE_MATCH = 12,
      MOUSE = 13,
      BUTTON = 14,
      SHADOW = 15,
      SMART_PEOPLE = 16,
      MISSILE_KILL_SEQ_DONE = 17
      NONE = 0,
      PLAYER = 1,
      DUMB_SPRITE_BOUNCER = 2,
      DUCK = 3,
      PIG = 4,
      KILL_SEQ_DONE_LEAVE_LAST_FRAME = 5,
      REPEAT = 6,
      KILL_SEQ_DONE = 7,
      TEXT_SPRITE = 8,
      MONSTER_DIAGONAL = 9,
      MONSTER_NONDIAGONAL = 10,
      MISSILE = 11,
      BRAIN_PARM_SIZE_MATCH = 12,
      MOUSE = 13,
      BUTTON = 14,
      SHADOW = 15,
      SMART_PEOPLE = 16,
      MISSILE_KILL_SEQ_DONE = 17

To assign a duck brain for example, one would use

myothersprite.brain = brain.DUCK
mysprite.brain = 10
myothersprite.brain = brain.DUCK
mysprite.brain = 10

Directions

Same as above except for directions:

      SOUTH_WEST = 1,
      SOUTH = 2,
      SOUTH_EAST = 3,
      WEST = 4,
      EAST = 6,
      NORTH_WEST = 7,
      NORTH = 8,
      NORTH_EAST = 9
      SOUTH_WEST = 1,
      SOUTH = 2,
      SOUTH_EAST = 3,
      WEST = 4,
      EAST = 6,
      NORTH_WEST = 7,
      NORTH = 8,
      NORTH_EAST = 9

And used similarly as a substitution for the raw numbers:

myothersprite.dir = direction.EAST
mysprite.dir = 8
myothersprite.dir = direction.EAST
mysprite.dir = 8

Editor sprite override types

      KILL_COMPLETELY = 1,
      DRAW_WITHOUT_HARDNESS = 2,
      DRAW_BACKGROUND_WITHOUT_HARDNESS = 3,
      DRAW_WITH_HARDNESS = 4,
      DRAW_BACKGROUND_WITH_HARDNESS = 5,
      KILL_RETURN_AFTER_FIVE_MINUTES = 6,
      KILL_RETURN_AFTER_THREE_MINUTES = 7,
      KILL_RETURN_AFTER_ONE_MINUTE = 8
      KILL_COMPLETELY = 1,
      DRAW_WITHOUT_HARDNESS = 2,
      DRAW_BACKGROUND_WITHOUT_HARDNESS = 3,
      DRAW_WITH_HARDNESS = 4,
      DRAW_BACKGROUND_WITH_HARDNESS = 5,
      KILL_RETURN_AFTER_FIVE_MINUTES = 6,
      KILL_RETURN_AFTER_THREE_MINUTES = 7,
      KILL_RETURN_AFTER_ONE_MINUTE = 8
mysprite.editor_sprite.type = editor_type.DRAW_WITH_HARDNESS
mysprite.editor_sprite.type = editor_type.DRAW_WITH_HARDNESS

etc

SFX global object

In 0.93 one has the ability to change the default sound effects for usually unalterable things such as ducks, pigs, the inventory, and the status bar.

To change these, one must use the "sfx" global object:

sfx.mouse.sound = 55
sfx.mouse.hz = 44100
sfx.mouse.sound = 55
sfx.mouse.hz = 44100

This will change the sound that plays on the title screen when one clicks on something that isn't a button sprite to sound slot 55 at 44.1kHz. Along with "mouse" there is also:

sfx.attack
sfx.warp
sfx.duck
sfx.pig
sfx.hurt
sfx.attack
sfx.warp
sfx.duck
sfx.pig
sfx.hurt

Which all have a corresponding sound and hz property for you to alter to your liking. In the case of the pigs, the set sound determines the lowest-numbered sound effect that will be played, meaning if set to 50, sounds 50 through to 54 will be used.

Similarly in the case of the hurt sound, it will be set sound +1 for the second hurt sound.

There is also one more in the base sfx table:

sfx.sprite_hz
sfx.sprite_hz

This determines the playback rate for sprites assigned a sound in the editor or via scripts which is 22KHz by default.

Much like the hz parameter for dink.playsound, setting hz to zero will cause a sound to be played back at its native speed, except for ducks and pigs which alter the playback rate depending on the size of the duck or pig.

For a size 100 duck or pig, the sample rate calculation is as follows:

duck_hz - (size * 50)
duck_hz - (size * 50)

Therefore, to play back at 44.1kHz, one should specify a sample rate of 49100 to sfx.duck.hz. The pigs will also apply an 800Hz variance to sound playback.

As the status bar, inventory, and choice menus have multiple sound effects to play back, they are grouped under sub-objects like so:

sfx.status.stats.hz = 0
sfx.status.gold.sound = 9
-- for when experience is incremented
sfx.status.exp_tick.sound = 44
-- when experience counts up after new level
sfx.status.exp_count.hz = 0

sfx.inventory.enter.sound = 60
sfx.inventory.move.sound = 61
sfx.inventory.select.sound = 62
sfx.inventory.exit.sound = 63

sfx.choice_menu.scroll.sound = 99
sfx.choice_menu.select.sound = 100
sfx.status.stats.hz = 0
sfx.status.gold.sound = 9
-- for when experience is incremented
sfx.status.exp_tick.sound = 44
-- when experience counts up after new level
sfx.status.exp_count.hz = 0

sfx.inventory.enter.sound = 60
sfx.inventory.move.sound = 61
sfx.inventory.select.sound = 62
sfx.inventory.exit.sound = 63

sfx.choice_menu.scroll.sound = 99
sfx.choice_menu.select.sound = 100

There are also two functions:

sfx.play(sound, hz, random, sprite, loop)
sfx.halt_all()
sfx.play(sound, hz, random, sprite, loop)
sfx.halt_all()

Note that sfx.play() does not return a sound object and is purely for one-shotting with.

Music global object

music.play("wanderer.ogg", 4000)
-- fade in ms param must be specified
music.play_mod_order(50)
music.pause()
music.resume()
music.stop()
music.fade_out(5000)
local muspos = music.position

local mybool = music.is_playing
music.volume = 128
music.tempo = 0.5
-- only a few music formats support tempo
music.play("wanderer.ogg", 4000)
-- fade in ms param must be specified
music.play_mod_order(50)
music.pause()
music.resume()
music.stop()
music.fade_out(5000)
local muspos = music.position

local mybool = music.is_playing
music.volume = 128
music.tempo = 0.5
-- only a few music formats support tempo

Second parameter to music_play is a fade-in, this is mandatory!